<!-- 数据切割组件 -->
<script setup name="MapBufferAnalysis">
import { onMounted, ref, onBeforeUnmount, nextTick, reactive, toRefs } from 'vue';
import { useRoute } from 'vue-router';
import { ElSlider, ElSelect, ElOption, ElMessage } from 'element-plus';
import { buffer as turfBuffer, point as turfPoint, bbox as turfBbox } from '@turf/turf';
import axios from 'axios';
import _ from 'lodash';
import mapboxGl from 'mapbox-gl';
import 'mapbox-gl-compare/dist/mapbox-gl-compare.css';
import { BASE_GEOSERVER_URL } from '@/apis';
import { getRelationById } from '@/apis/api-map-server';
import { load } from '@/common/common-loading';
import BorderBoxBg from '@/components/BorderBoxBg.vue';
import { GET_MAPBOX_MAP } from '@/utils/map-utils';
import BufferQueryResultPolygon from './BufferQueryResultPolygon.vue';

let marker, pointPos;
const unitsList = [
  // { label: '毫米', value: 'millimeters' },
  // { label: '厘米', value: 'centimeters' },
  { label: '米', value: 'meters' },
  { label: '公里', value: 'kilometers' },
  { label: '英里', value: 'miles' },
  { label: '海里', value: 'nauticalmiles' },
  { label: '英寸', value: 'inches' },
  { label: '码', value: 'yards' },
  { label: '英尺', value: 'feet' },
  // { label: '弧度', value: 'radians' },
  // { label: '度', value: 'degrees' },
];
const unitss = {
  meters: {
    max: 10000,
  },
  kilometers: {
    max: 10,
  },
  miles: {
    max: 10,
  },
  nauticalmiles: {
    max: 10,
  },
  inches: {
    max: 1000,
  },
  yards: {
    max: 1000,
  },
  feet: {
    max: 1000,
  },
};
const route = useRoute();
const emit = defineEmits(['close']);

const props = defineProps({
  toolbarRight: {
    type: String,
    default: '5.3125rem',
  },
});
const { toolbarRight } = toRefs(props);

const analysisObject = reactive({
  size: 1,
  units: 'kilometers',
  max: 100,
});
const mapImgList = ref([]);
const baseBufferArea = ref([]);
const queryShow = ref(false);
const queryData = ref([]);

const WFSQuery = async (val) => {
  if (!val.coordinates.length) return ElMessage.warning('请选择分析缓冲区');
  load.show('正在分析信息，请稍等...');

  let p = mapImgList.value.map(async (item) => {
    let res = await axios.get(
      `${BASE_GEOSERVER_URL}/st_server_api/nikwfs/wfssev/?id=${
        item.id
      }&REQUEST=GetFeature&SERVICE=WFS&VERSION=1.1.0&TYPENAME=${
        item.TYPENAME
      }&MAXFEATURES=999999&SRSNAME=EPSG:4326&FILTER=${`INTERSECTS( EPSG:4326%3B+POLYGON((${String(
        _.chunk(_.flattenDeep(val.coordinates), 2)
          .map((e) => e.join(' '))
          .join(', '),
      )})))`}`,
    );

    return {
      ...res,
      columns: item.columns,
      url: item.url,
    };
  });

  Promise.all(p)
    .then((res) => {
      let arr = [];

      for (var i = 0; i < res.length; i++) {
        const { data, status, columns, url } = res[i];

        if (status === 200) {
          const { features } = data;

          arr.push({
            ...data,
            tableData: features.map((el) => {
              return {
                id: el.id,
                ...el.properties,
              };
            }),
            columns: columns,
            url,
          });
        }
      }

      queryData.value = arr;

      ElMessage({
        message: '查询成功',
        duration: 1000,
        type: 'success',
      });

      queryShow.value = true;
    })
    .catch(() => {
      queryShow.value = false;
    })
    .finally(() => {
      load.hide();
    });
};

const getRelationByIdApi = async () => {
  const [err, data] = await getRelationById({
    menuCode: route.query?.code,
  });

  if (!err) {
    let arr = [];

    for (var i = 0; i < data.length; i++) {
      const el = data[i];

      for (var l = 0; l < el.children.length; l++) {
        const item = el.children[l];

        arr.push({
          TYPENAME: item.layerMeta.name.replace('.shp', ''),
          id: el.id,
          columns: item.layerMeta.fields.map((item) => {
            return {
              key: item.name,
              label: item.name,
              title: item.name,
              dataKey: item.name,
              width: 150,
            };
          }),
          url: `${BASE_GEOSERVER_URL}/st_server_api/service/niktile/?x={x}&y={y}&z={z}&id=${el.id}&lyrname=${item.layerMeta.name}`,
        });
      }
    }

    mapImgList.value = arr;
  }
};

// 关闭弹窗 并清理数据
const handleClose = () => {
  let map = GET_MAPBOX_MAP();

  let source = map.getSource('bufferArea');

  if (source) {
    map.removeLayer('bufferArea');
    map.removeSource('bufferArea');
  }

  marker && marker.remove();

  emit('close', false);
};

// 地图选点
const pointFunction = (e) => {
  const map = GET_MAPBOX_MAP();

  pointPos = [e.lngLat.lng, e.lngLat.lat];

  let source = map.getSource('bufferArea');

  const bufferArea = turfBuffer(turfPoint(pointPos), analysisObject.size, { units: analysisObject.units });

  if (source) {
    source.setData(bufferArea);
  } else {
    map.addSource('bufferArea', {
      type: 'geojson',
      data: bufferArea,
    });
    map.addLayer({
      id: 'bufferArea',
      type: 'fill',
      source: 'bufferArea',
      paint: {
        // 绘制类属性
        'fill-antialias': true, // 填充时是否反锯齿（可选，默认值为 true）
        'fill-opacity': 1, // 填充的不透明度（可选，取值范围为 0 ~ 1，默认值为 1）
        'fill-pattern': '', // 填充用的图案（可选，这里填写在 sprite 雪碧图中图标名称。为了图案能无缝填充，图标的高宽需要是 2 的倍数）
        'fill-color': 'rgba(255,0,0,.2)', // 填充的颜色（可选，默认值为 #000000。如果设置了 fill-pattern，则 fill-color 将无效）
        'fill-outline-color': '#f00', // 描边的颜色（可选，默认和 fill-color 一致。如果设置了 fill-pattern，则 fill-outline-color 将无效。为了使用此属性，还需要设置 fill-antialias 为 true）
        'fill-translate': [0, 0], // 填充的平移（可选，通过平移 [x, y] 达到一定的偏移量。默认值为 [0, 0]，单位：像素。）
        'fill-translate-anchor': 'map', // 平移的锚点，即相对的参考物（可选，可选值为 map、viewport，默认为 map）
      },
    });
  }

  marker && marker.remove();
  baseBufferArea.value = bufferArea.geometry.coordinates;
  nextTick(() => {
    marker = new mapboxGl.Marker().setLngLat(pointPos).addTo(map);
    map.fitBounds(turfBbox(bufferArea), { padding: 100, maxZoom: 18, duration: 1000 });
  });
};

// 地图选点事件挂载
const mapGetPoint = () => {
  const map = GET_MAPBOX_MAP();

  map.off('click', pointFunction);
  nextTick(() => {
    map.on('click', pointFunction);
  });
};

// 改变半径尺寸 改变单位
const handleFormChange = (e) => {
  const map = GET_MAPBOX_MAP();
  let source = map.getSource('bufferArea');

  if (!marker && !source) return;

  let size = unitss[e]?.max || analysisObject.size;

  if (unitss[e]) {
    analysisObject.max = unitss[e].max;
  }

  const bufferArea = turfBuffer(turfPoint(pointPos), Math.min(size, analysisObject.size), {
    units: analysisObject.units,
  });

  source.setData(bufferArea);
  map.fitBounds(turfBbox(bufferArea), { padding: 100, maxZoom: 18, duration: 1000 });

  baseBufferArea.value = bufferArea.geometry.coordinates;
};

// 开始提交分析
const handleAnalysis = () => {
  WFSQuery({ coordinates: baseBufferArea.value });
};

onMounted(() => {
  getRelationByIdApi();
});

onBeforeUnmount(() => {
  // handleClose();
  let map = GET_MAPBOX_MAP();

  map.off('click', pointFunction);
});
</script>
<template>
  <BorderBoxBg title="数据分析" class="analysis" :right="toolbarRight" @close="handleClose">
    <div class="analysis-buffer">
      <div class="type-item" @click="mapGetPoint">
        <div>地图选点</div>
      </div>
      <div class="forms-item">
        <label>半径单位：</label>
        <ElSelect
          v-model="analysisObject.units"
          placeholder="Select"
          size="large"
          style="width: 240px"
          @change="handleFormChange"
        >
          <ElOption v-for="item in unitsList" :key="item" :label="item.label" :value="item.value" />
        </ElSelect>
      </div>
      <div class="forms-item">
        <label>缓冲半径：</label
        ><ElSlider
          v-model="analysisObject.size"
          style="width: 240px"
          :min="0"
          :max="analysisObject.max"
          show-input
          @change="handleFormChange"
        />
      </div>
    </div>
    <div class="submit" @click="handleAnalysis"><div>开始分析</div></div>
    <BufferQueryResultPolygon
      v-if="queryShow"
      :result-features="queryData"
      :polygon-show="queryShow"
      @close="
        () => {
          queryShow = false;
        }
      "
    ></BufferQueryResultPolygon>
  </BorderBoxBg>
</template>

<style scoped lang="scss">
.analysis {
  top: 60%;
  bottom: auto;
  width: 400px;
  .analysis-buffer {
    display: flex;
    flex-direction: column;
    gap: 20px;
    justify-content: center;
    padding: 20px;
    .type-item {
      height: 40px;
      // margin: 0 20px;
      line-height: 40px;
      text-align: center;
      background-color: #0dc4c49d;
      border-radius: 5px;
      cursor: pointer;
    }
    .type-item:hover {
      background-color: #0dc4c4e0;
    }
  }
  .submit {
    display: flex;
    justify-content: center;
    width: 100%;
    > div {
      width: 200px;
      height: 40px;
      margin: 0 20px;
      line-height: 40px;
      text-align: center;
      background-color: #0dc4c49d;
      border-radius: 5px;
      cursor: pointer;
    }
    > div:hover {
      background-color: #0dc4c4e0;
    }
  }
  .forms-item {
    display: flex;
    align-items: center;
    > label {
      width: 100px;
    }
  }
}
</style>
<style lang="scss">
.el-cascader__dropdown.el-popper {
  li {
    color: #fff;
  }

  .el-cascader-node.in-active-path,
  .el-cascader-node.is-selectable.in-checked-path,
  .el-cascader-node.is-active {
    color: var(--el-cascader-menu-selected-text-color);
  }

  .el-cascader-node:not(.is-disabled):hover,
  .el-cascader-node:not(.is-disabled):focus {
    color: rgb(17, 222, 230);
  }
}

.el-cascader__dropdown.el-popper .el-popper__arrow::before {
  background-color: rgba(0, 69, 93, 0.6);
  border-color: rgba(0, 69, 93, 0.6);
}

.el-cascader-menu {
  border-right-color: rgba(0, 69, 93, 1);
}
</style>
